package com.tsy.pointcloud.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tsy.common.annotation.Anonymous;
import com.tsy.common.annotation.Log;
import com.tsy.common.config.TSYConfig;
import com.tsy.common.constant.PointCloudConstants;
import com.tsy.common.core.controller.BaseController;
import com.tsy.common.core.domain.AjaxResult;
import com.tsy.common.core.page.TableDataInfo;
import com.tsy.common.enums.BusinessType;
import com.tsy.common.exception.ServiceException;
import com.tsy.common.utils.SecurityUtils;
import com.tsy.common.utils.converter.PointCloudUtil;
import com.tsy.common.utils.file.FileUploadUtils;
import com.tsy.common.utils.file.FileUtils;
import com.tsy.framework.config.ServerConfig;
import com.tsy.pointcloud.domain.FileInfo;
import com.tsy.pointcloud.domain.dto.UploadResultDto;
import com.tsy.pointcloud.service.FileInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.File;
import java.util.*;

import static org.springframework.data.domain.ExampleMatcher.GenericPropertyMatchers.contains;

/**
 * 通用请求处理
 * 
 * @author tsy
 */
@Slf4j
@Validated
@RestController
@RequestMapping("/pointcloud")
public class PointCloudController extends BaseController {

    @Autowired
    private ServerConfig serverConfig;

    @Value(value = "${tsy.profile}")
    private String basePath;

    /**
     * 点云切片文件路径
     */
    private static final String CONVERTER_FOLDER = "converter";

    @Autowired
    private FileInfoService fileInfoService;

    /**
     * 点云文件上传和处理
     */
    @PostMapping("/upload")
    public AjaxResult uploadFile(MultipartFile file) {
        try {
            // 上传文件路径
            String filePath = TSYConfig.getUploadPath();
            // 上传并返回新文件名称
            String fileName = FileUploadUtils.upload(filePath, file);
            String nameNotSuffix = FileUtils.getNameNotSuffix(fileName);
            String srcPath = fileName.replace("/profile", basePath);
            String destPath = basePath + File.separator + CONVERTER_FOLDER + File.separator + nameNotSuffix;
            PointCloudUtil.pintCloudConverter(srcPath, destPath);
            String url = serverConfig.getUrl();
            AjaxResult ajax = AjaxResult.success();
            // http://127.0.0.1:8082/profile/converter/test_20250324151204A004/metadata.json
            ajax.put("url", url + "/profile/" + CONVERTER_FOLDER + "/" + nameNotSuffix + "/metadata.json");
            ajax.put("fileName", fileName);
            ajax.put("newFileName", FileUtils.getName(fileName));
            ajax.put("originalFilename", file.getOriginalFilename());
            return ajax;
        }
        catch (Exception e)
        {
            return AjaxResult.error(e.getMessage());
        }
    }



    /**
     * 通过md5查询
     */
    @GetMapping("/findByMd5")
    public AjaxResult findByMd5(@NotBlank(message = "文件MD5不能为空") String fileMd5, @NotBlank(message = "文件名不能为空") String fileName) {

        UploadResultDto uploadResultDto = fileInfoService.findByMd5(fileMd5, fileName);

        return AjaxResult.success(uploadResultDto);
    }

    /**
     * 分片上传
     */
    @PostMapping("/fragmentUpload")
    @Log(title = "点云文件上传", businessType = BusinessType.INSERT)
    public AjaxResult fragmentUpload(
            @NotNull(message = "文件不能为空") MultipartFile file,
            @NotBlank(message = "文件名不能为空") String fileName,
            @NotBlank(message = "文件MD5不能为空") String fileMd5,
            @NotNull(message = "分片索引不能为空") Integer chunkIndex,
            @NotNull(message = "总分片数不能为空") Integer chunks) {

        // 校验文件类型
        String[] suffixArr = new String[]{".ply", ".laz", ".las", ".pcd"};
        if (!Arrays.stream(suffixArr).anyMatch(suffix -> suffix.equals(FileUtils.getFileType(fileName).toLowerCase()))) {
            throw new ServiceException("文件类型错误！");
        }

        // 校验文件名
        int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
        if (fileNamelength > PointCloudConstants.DEFAULT_FILE_NAME_LENGTH) {
            throw new ServiceException("文件名超过最大长度！");
        }

        // 校验分片文件大小
        if (file.getSize() > PointCloudConstants.DEFAULT_MAX_SIZE) {
            throw new ServiceException("文件最大大小50M！");
        }

        UploadResultDto resultDto = fileInfoService.fragmentUpload(file, fileName, fileMd5, chunkIndex, chunks);

        return AjaxResult.success(resultDto);
    }

    /**
     * 点云列表
     */
    @GetMapping("/list")
    public TableDataInfo list() {
        startPage();
        LambdaQueryWrapper<FileInfo> queryWrapper = Wrappers.lambdaQuery(FileInfo.class)
                .eq(FileInfo::getStatus, 1)
                .eq(FileInfo::getUserId, SecurityUtils.getUserId())
                .orderByAsc(SecurityUtils.getUserId() == 100L, FileInfo::getOriginalName)
                .orderByDesc(FileInfo::getUpdateTime);

        List<FileInfo> list = fileInfoService.list(queryWrapper);
        return getDataTable(list);
    }

    /**
     * 删除点云
     */
    @DeleteMapping("/delete")
    @Log(title = "点云删除", businessType = BusinessType.DELETE)
    public AjaxResult delete(@NotNull(message = "文件ID不能为空") Long id) {
        fileInfoService.delete(id);
        return AjaxResult.success();
    }

    /**
     * 点云处理
     */
    @PostMapping("/handle")
    @Log(title = "点云分割处理", businessType = BusinessType.UPDATE)
    public AjaxResult handle(@NotBlank(message = "文件名不能为空") String fileName, @NotBlank(message = "文件MD5不能为空") String fileMd5) {
        Long userId = SecurityUtils.getUserId();
        fileInfoService.handle(fileName, fileMd5, userId);
        return AjaxResult.success();
    }

    /**
     * 轨道点云导出为矢量
     */
    @PostMapping("/exportRailwayVector")
    @Log(title = "轨道点云导出为矢量", businessType = BusinessType.EXPORT)
    public AjaxResult exportRailwayVector(@NotBlank(message = "文件名不能为空") String fileName, @NotBlank(message = "文件MD5不能为空") String fileMd5) {
        Long userId = SecurityUtils.getUserId();
        fileInfoService.exportRailwayVector(fileName, fileMd5, userId);
        return AjaxResult.success();
    }

}
